import geopandas as gpd
import matplotlib.pyplot as plt
import os
import numpy as np
from dash import html, dcc
import plotly.graph_objects as go
import pandas as pd

# 设置支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 1. 读取GeoJSON文件
gdf = gpd.read_file(r'.\assets\map\huangpuqu.geojson')  # 替换为实际文件路径
if gdf.crs != 'EPSG:3857': 
    gdf = gdf.to_crs('EPSG:3857') 

# 2. 检查数据坐标系（若坐标系缺失或非投影坐标系，需转换）
if gdf.crs is None:
    gdf = gdf.set_crs('EPSG:4326')  # 设置为WGS84地理坐标系（经度/纬度）
elif gdf.crs != 'EPSG:3857':  # 若需要Web墨卡托投影（用于在线地图叠加）
    gdf = gdf.to_crs('EPSG:3857')

# 3. 绘制基础地图
plt.figure(figsize=(10, 8))
ax = plt.gca()
gdf.plot(
    ax=ax,                # 使用当前坐标轴
    edgecolor='k',        # 边界颜色为黑色
    facecolor='#ADD8E6',  # 填充颜色为浅蓝色
    alpha=0.2,            # 设置透明度为20%（即80%透明）
    linewidth=1.0         # 边界线宽度
)

def create_interactive_map(org_data):
    """
    创建交互式地图，显示组织位置和设备数量
    """
    # 创建底图
    fig = go.Figure()
    
    # 添加黄浦区街道边界
    try:
        # 尝试从文件加载
        try:
            streets_gdf = gpd.read_file(r'.\assets\map\huangpu_streets.geojson')
            if streets_gdf.crs != 'EPSG:3857':
                streets_gdf = streets_gdf.to_crs('EPSG:3857')
        except:
            # 如果文件不存在，使用简化数据
            print("使用简化街道数据")
            streets_gdf = create_simplified_streets()
        
        # 定义街道颜色列表 - 使用不同深浅的蓝绿色系
        colors = [
            '#003366', '#004080', '#0059b3', '#0073e6', '#1a8cff',
            '#4da6ff', '#80bfff', '#006666', '#009999', '#00cccc',
            '#00ffff', '#2eb8b8', '#5cdada', '#8cecec', '#006633'
        ]
        
        # 绘制每个街道
        for idx, row in streets_gdf.iterrows():
            street_name = row.get('name', f'街道{idx+1}')  # 获取街道名称
            color_idx = idx % len(colors)  # 循环使用颜色
            
            if row.geometry.geom_type == 'MultiPolygon':
                for geom in row.geometry.geoms:
                    x, y = geom.exterior.xy
                    x_list = list(x)
                    y_list = list(y)
                    fig.add_trace(go.Scatter(
                        x=x_list,
                        y=y_list,
                        mode='lines',
                        line=dict(color='white', width=2),  # 白色边界线
                        fill='toself',
                        fillcolor=colors[color_idx],  # 使用不同颜色填充
                        opacity=0.7,  # 设置透明度
                        name=street_name,
                        hoverinfo='name',
                        showlegend=False
                    ))
            else:
                x, y = row.geometry.exterior.xy
                x_list = list(x)
                y_list = list(y)
                fig.add_trace(go.Scatter(
                    x=x_list,
                    y=y_list,
                    mode='lines',
                    line=dict(color='white', width=2),  # 白色边界线
                    fill='toself',
                    fillcolor=colors[color_idx],  # 使用不同颜色填充
                    opacity=0.7,  # 设置透明度
                    name=street_name,
                    hoverinfo='name',
                    showlegend=False
                ))
        
        print("黄浦区街道边界加载成功")
    except Exception as e:
        print(f"无法加载黄浦区街道边界: {str(e)}")
        # 如果无法加载街道边界，则加载区边界
        try:
            gdf = gpd.read_file(r'.\assets\map\huangpuqu.geojson')
            if gdf.crs != 'EPSG:3857':
                gdf = gdf.to_crs('EPSG:3857')
            
            # 提取边界坐标
            for idx, row in gdf.iterrows():
                # 获取多边形坐标
                if row.geometry.geom_type == 'MultiPolygon':
                    for geom in row.geometry.geoms:
                        x, y = geom.exterior.xy
                        x_list = list(x)
                        y_list = list(y)
                        fig.add_trace(go.Scatter(
                            x=x_list,
                            y=y_list,
                            mode='lines',
                            line=dict(color='white', width=3),
                            fill='toself',
                            fillcolor='#003366',  # 深蓝色填充
                            opacity=0.7,
                            hoverinfo='skip',
                            showlegend=False
                        ))
                else:
                    x, y = row.geometry.exterior.xy
                    x_list = list(x)
                    y_list = list(y)
                    fig.add_trace(go.Scatter(
                        x=x_list,
                        y=y_list,
                        mode='lines',
                        line=dict(color='white', width=3),
                        fill='toself',
                        fillcolor='#003366',  # 深蓝色填充
                        opacity=0.7,
                        hoverinfo='skip',
                        showlegend=False
                    ))
            print("黄浦区边界加载成功")
        except Exception as e:
            print(f"无法加载黄浦区边界: {str(e)}")
            # 使用简化的矩形边界
            boundary_coords = [
                [13520000, 3657500], [13525000, 3657500],
                [13525000, 3664000], [13520000, 3664000],
                [13520000, 3657500]
            ]
            x, y = zip(*boundary_coords)
            fig.add_trace(go.Scatter(
                x=x, y=y,
                mode='lines',
                line=dict(color='white', width=3),
                fill='toself',
                fillcolor='#003366',  # 深蓝色填充
                opacity=0.7,
                hoverinfo='skip',
                showlegend=False
            ))
            print("使用简化边界代替")
    
    # 添加组织标记点
    for org in org_data:
        fig.add_trace(go.Scatter(
            x=[org['location'][0]],
            y=[org['location'][1]],
            mode='markers+text',
            marker=dict(
                size=org['count'] / 50 + 10,
                color='#FF6600',  # 橙色标记点
                line=dict(width=2, color='white')  # 添加白色边框使其在深色背景上更明显
            ),
            text=f"{org['name']}<br>{org['count']}台",
            textposition="top center",
            textfont=dict(size=14, color='white', family='SimHei'),  # 白色文字在深色背景上更清晰
            name=org['name'],
            customdata=[org['id']],
            hoverinfo='text',
            hovertext=f"<b>{org['name']}</b><br>设备数量: {org['count']}台<br>点击查看详情"
        ))
    
    # 添加指南针/方向标识
    fig.add_annotation(
        x=13520500, y=3663500,
        text="<b>南</b>     <b>北</b>",
        showarrow=False,
        font=dict(color="white", size=12),
        bgcolor="rgba(0,0,0,0.5)",
        bordercolor="white",
        borderwidth=1,
        borderpad=4,
        opacity=0.8
    )
    
    # 添加水系标识
    fig.add_annotation(
        x=13522500, y=3657700,
        text="<b>黄浦江</b>",
        showarrow=False,
        font=dict(color="#80bfff", size=14),
        opacity=0.9
    )
    
    # 设置布局
    fig.update_layout(
        title='黄浦区医疗机构设备分布',
        autosize=True,
        height=600,
        showlegend=False,
        margin=dict(l=0, r=0, t=30, b=0),
        xaxis=dict(
            range=[13520000, 13525000],
            showgrid=False,
            zeroline=False,
            visible=False
        ),
        yaxis=dict(
            range=[3657500, 3664000],
            showgrid=False,
            zeroline=False,
            visible=False,
            scaleanchor="x",
            scaleratio=1
        ),
        plot_bgcolor='#001a33',  # 深蓝色背景
        paper_bgcolor='#001a33',  # 深蓝色背景
    )
    
    return fig


# 如果没有街道GeoJSON文件，可以添加这个函数来创建简化的街道数据
def create_simplified_streets():
    """创建简化的黄浦区街道数据"""
    # 定义街道名称和大致边界坐标
    streets_data = [
        {"name": "南京东路", "coords": [
            [13522500, 3662500], [13524000, 3662500], 
            [13524000, 3661500], [13522500, 3661500]
        ]},
        {"name": "外滩", "coords": [
            [13524000, 3662500], [13525000, 3662500], 
            [13525000, 3660500], [13524000, 3660500]
        ]},
        {"name": "豫园", "coords": [
            [13524000, 3660500], [13525000, 3660500], 
            [13525000, 3659000], [13524000, 3659000]
        ]},
        {"name": "小东门", "coords": [
            [13523000, 3660000], [13524000, 3660000], 
            [13524000, 3659000], [13523000, 3659000]
        ]},
        {"name": "淮海中路", "coords": [
            [13521500, 3660500], [13523000, 3660500], 
            [13523000, 3659500], [13521500, 3659500]
        ]},
        {"name": "老西门", "coords": [
            [13522000, 3659500], [13523500, 3659500], 
            [13523500, 3658000], [13522000, 3658000]
        ]},
        {"name": "打浦桥", "coords": [
            [13520500, 3659000], [13522000, 3659000], 
            [13522000, 3657500], [13520500, 3657500]
        ]},
        {"name": "半淞园", "coords": [
            [13521500, 3659500], [13522500, 3659500], 
            [13522500, 3658500], [13521500, 3658500]
        ]},
        {"name": "五里桥", "coords": [
            [13520000, 3659500], [13521500, 3659500], 
            [13521500, 3658000], [13520000, 3658000]
        ]},
        {"name": "瑞金二路", "coords": [
            [13521000, 3662000], [13522500, 3662000], 
            [13522500, 3661000], [13521000, 3661000]
        ]}
    ]
    
    # 创建GeoDataFrame
    from shapely.geometry import Polygon
    geometries = [Polygon(street["coords"]) for street in streets_data]
    names = [street["name"] for street in streets_data]
    
    streets_gdf = gpd.GeoDataFrame({"name": names, "geometry": geometries}, crs="EPSG:3857")
    return streets_gdf

# 在文件末尾添加以下代码

# 7. 美化图表
plt.title('黄浦区地图及主要道路', fontsize=14, fontweight='bold')
plt.xlabel('经度')
plt.ylabel('纬度')
plt.axis('on')  # 显示坐标轴
plt.tight_layout()  # 自动调整布局

# 确保输出目录存在
output_dir = r'e:\assetms\assets\map'
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 保存高分辨率图片
plt.savefig(r'e:\assetms\assets\map\huangpu_map_static.png', dpi=300, bbox_inches='tight', transparent=True)
# plt.show()  # 显示静态地图

# 测试交互式地图功能
if __name__ == "__main__":
    # 示例组织数据
    sample_org_data = [
        {"id": 1, "name": "瑞金二路", "location": [13521800, 3661800], "count": 120},
        {"id": 2, "name": "小东门", "location": [13523500, 3659500], "count": 150},
        {"id": 3, "name": "南京东路", "location": [13523800, 3661800], "count": 101},
        {"id": 4, "name": "淮海中路", "location": [13522500, 3660200], "count": 108},
        {"id": 5, "name": "打浦桥", "location": [13521500, 3658000], "count": 433},
        {"id": 6, "name": "外滩", "location": [13525000, 3661800], "count": 181},
        {"id": 7, "name": "老西门", "location": [13522500, 3659000], "count": 341},
        {"id": 8, "name": "豫园", "location": [13525000, 3659800], "count": 306},
        {"id": 9, "name": "五里桥", "location": [13521000, 3658500], "count": 196},
        {"id": 10, "name": "半淞园", "location": [13522000, 3658500], "count": 186},
        {"id": 11, "name": "顺昌", "location": [13521000, 3658000], "count": 186}
    ]
    
    # 创建交互式地图
    fig = create_interactive_map(sample_org_data)
    
    # 保存交互式地图为PNG文件
    import plotly.io as pio
    # 保存为HTML文件（可选）
    pio.write_html(fig, r'e:\assetms\assets\map\huangpu_interactive_map.html')
    
    # 保存为PNG文件
    pio.write_image(fig, r'e:\assetms\assets\map\huangpu_interactive_map.png', 
                    width=1200, height=800, scale=2)  # 设置更高的分辨率
    
    print("地图生成完成！")
    print(f"静态地图已保存至: e:\\assetms\\assets\\map\\huangpu_map_static.png")
    print(f"交互式地图已保存至: e:\\assetms\\assets\\map\\huangpu_interactive_map.html")
    print(f"交互式地图PNG已保存至: e:\\assetms\\assets\\map\\huangpu_interactive_map.png")